diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-02-14 15:52:29 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-02-14 15:52:29 +0700 |
| commit | cce0ab7c8bf657b8dbe804e30fd7851ff9c26414 (patch) | |
| tree | e5b738169a6c87701f8b8d2763a5c0ebdd4734f8 /src/pages/shop/product/[slug].js | |
| parent | 8dc379e37d7ab3b86725b58d9636c4ad64dcfc2f (diff) | |
no message
Diffstat (limited to 'src/pages/shop/product/[slug].js')
| -rw-r--r-- | src/pages/shop/product/[slug].js | 235 |
1 files changed, 128 insertions, 107 deletions
diff --git a/src/pages/shop/product/[slug].js b/src/pages/shop/product/[slug].js index 60849264..61692c1c 100644 --- a/src/pages/shop/product/[slug].js +++ b/src/pages/shop/product/[slug].js @@ -1,43 +1,43 @@ -import Link from "@/components/elements/Link"; -import { useRouter } from "next/router"; -import { useEffect, useState } from "react"; -import Header from "@/components/layouts/Header"; -import apiOdoo from "@/core/utils/apiOdoo"; -import { createSlug, getIdFromSlug } from "@/core/utils/slug"; -import currencyFormat from "@/core/utils/currencyFormat"; -import Layout from "@/components/layouts/Layout"; -import { createOrUpdateItemCart } from "@/core/utils/cart"; -import toast from "react-hot-toast"; -import Footer from "@/components/layouts/Footer"; -import Image from "@/components/elements/Image"; -import LineDivider from "@/components/elements/LineDivider"; -import { HeartIcon as HeartIconSolid } from "@heroicons/react/24/solid"; -import { useAuth } from "@/core/utils/auth"; -import { HeartIcon } from "@heroicons/react/24/outline"; -import LazyLoad from "react-lazy-load"; -import ProductSimilar from "@/components/products/ProductSimilar"; +import Link from "@/components/elements/Link" +import { useRouter } from "next/router" +import { useEffect, useState } from "react" +import Header from "@/components/layouts/Header" +import apiOdoo from "@/core/utils/apiOdoo" +import { createSlug, getIdFromSlug } from "@/core/utils/slug" +import currencyFormat from "@/core/utils/currencyFormat" +import Layout from "@/components/layouts/Layout" +import { createOrUpdateItemCart } from "@/core/utils/cart" +import toast from "react-hot-toast" +import Footer from "@/components/layouts/Footer" +import Image from "@/components/elements/Image" +import LineDivider from "@/components/elements/LineDivider" +import { HeartIcon as HeartIconSolid } from "@heroicons/react/24/solid" +import { useAuth } from "@/core/utils/auth" +import { HeartIcon } from "@heroicons/react/24/outline" +import LazyLoad from "react-lazy-load" +import ProductSimilar from "@/components/products/ProductSimilar" export async function getServerSideProps( context ) { - const { slug } = context.query; - let product = await apiOdoo('GET', '/api/v1/product/' + getIdFromSlug(slug)); + const { slug } = context.query + let product = await apiOdoo('GET', '/api/v1/product/' + getIdFromSlug(slug)) if (product?.length == 1) { - product = product[0]; - product.description = product.description.replaceAll('<p>', '||p||'); - product.description = product.description.replaceAll('</p>', '||/p||'); - product.description = product.description.replace(/(<([^>]+)>)/gi, ' '); - product.description = product.description.replaceAll('||p||', '<p>'); - product.description = product.description.replaceAll('||/p||', '</p>'); - product.description = product.description.trim(); + product = product[0] + product.description = product.description.replaceAll('<p>', '||p||') + product.description = product.description.replaceAll('</p>', '||/p||') + product.description = product.description.replace(/(<([^>]+)>)/gi, ' ') + product.description = product.description.replaceAll('||p||', '<p>') + product.description = product.description.replaceAll('||/p||', '</p>') + product.description = product.description.trim() } - return { props: { product } }; + return { props: { product } } } export default function ProductDetail({ product }) { - const [ auth ] = useAuth(); - const router = useRouter(); - const { slug } = router.query; - const [selectedVariant, setSelectedVariant] = useState(""); - const [quantity, setQuantity] = useState("1"); + const [ auth ] = useAuth() + const router = useRouter() + const { slug } = router.query + const [selectedVariant, setSelectedVariant] = useState("") + const [quantity, setQuantity] = useState("1") const [activeVariant, setActiveVariant] = useState({ id: product.id, code: product.code, @@ -45,51 +45,52 @@ export default function ProductDetail({ product }) { stock: product.stock_total, weight: product.weight, attributes: '', - }); + }) - const [ isAddedToWishlist, setAddedToWishlist ] = useState(false); + const [ isAddedToWishlist, setAddedToWishlist ] = useState(false) + const [ activeTab, setActiveTab ] = useState('specification') const addOrDeleteWishlist = async () => { if (auth) { await apiOdoo('POST', `/api/v1/user/${auth.id}/wishlist/create-or-delete`, { product_id: product.id - }); + }) if (isAddedToWishlist) { - toast.success('Berhasil menghapus dari wishlist'); + toast.success('Berhasil menghapus dari wishlist') } else { - toast.success('Berhasil menambahkan ke wishlist'); + toast.success('Berhasil menambahkan ke wishlist') } - setAddedToWishlist(!isAddedToWishlist); + setAddedToWishlist(!isAddedToWishlist) } else { - toast.error('Login terlebih dahulu untuk melanjutkan'); - router.push('/login'); + toast.error('Login terlebih dahulu untuk melanjutkan') + router.push('/login') } - }; + } useEffect(() => { if (auth) { const checkWishlist = async () => { - const wishlist = await apiOdoo('GET', `/api/v1/user/${auth.id}/wishlist?product_id=${product.id}`); - setAddedToWishlist(wishlist.product_total > 0 ? true : false); + const wishlist = await apiOdoo('GET', `/api/v1/user/${auth.id}/wishlist?product_id=${product.id}`) + setAddedToWishlist(wishlist.product_total > 0 ? true : false) } - checkWishlist(); + checkWishlist() } - }, [ auth, product ]); + }, [ auth, product ]) useEffect(() => { if (product.variants.length == 1) { - setSelectedVariant(product.variants[0].id); + setSelectedVariant(product.variants[0].id) } - }, [ product ]); + }, [ product ]) useEffect(() => { if (selectedVariant != '') { let newActiveVariant = product.variants.filter((variant) => { - return variant.id == selectedVariant; - }); + return variant.id == selectedVariant + }) if (newActiveVariant.length == 1) { - newActiveVariant = newActiveVariant[0]; + newActiveVariant = newActiveVariant[0] setActiveVariant({ id: newActiveVariant.id, code: newActiveVariant.code, @@ -97,55 +98,65 @@ export default function ProductDetail({ product }) { stock: newActiveVariant.stock, weight: newActiveVariant.weight, attributes: newActiveVariant.attributes.join(', '), - }); + }) } } - }, [selectedVariant, product]); + }, [selectedVariant, product]) const onchangeVariant = (e) => { - setSelectedVariant(e.target.value); + setSelectedVariant(e.target.value) } const onChangeQuantity = (e) => { - let inputValue = e.target.value; - inputValue = parseInt(inputValue); - inputValue = Math.floor(inputValue); - setQuantity(inputValue); + let inputValue = e.target.value + inputValue = parseInt(inputValue) + inputValue = Math.floor(inputValue) + setQuantity(inputValue) } const addItemToCart = () => { if (product.variant_total > 1 && !selectedVariant) { - toast.error('Pilih varian terlebih dahulu untuk menambahkan ke keranjang', { duration: 2000 }); - return false; + toast.error('Pilih varian terlebih dahulu untuk menambahkan ke keranjang', { duration: 2000 }) + return false } if (quantity > 0) { - toast.success('Berhasil menambahkan ke keranjang', { duration: 1500 }); - createOrUpdateItemCart(activeVariant.id, parseInt(quantity)); + toast.success('Berhasil menambahkan ke keranjang', { duration: 1500 }) + createOrUpdateItemCart(activeVariant.id, parseInt(quantity)) } else { - toast.error('Jumlah barang yang ditambahkan minimal 1 pcs', { duration: 2000 }); + toast.error('Jumlah barang yang ditambahkan minimal 1 pcs', { duration: 2000 }) } - return true; + return true } const checkoutProduct = () => { if (!auth) { - toast.error('Login terlebih dahulu untuk melanjutkan', { duration: 2000 }); - router.push('/login'); - return; + toast.error('Login terlebih dahulu untuk melanjutkan', { duration: 2000 }) + router.push('/login') + return } if (product.variant_total > 1 && !selectedVariant) { - toast.error('Pilih varian terlebih dahulu untuk melanjutkan pembelian', { duration: 2000 }); - return; + toast.error('Pilih varian terlebih dahulu untuk melanjutkan pembelian', { duration: 2000 }) + return } if (quantity < 0) { - toast.error('Jumlah barang yang ditambahkan minimal 1 pcs', { duration: 2000 }); - return; + toast.error('Jumlah barang yang ditambahkan minimal 1 pcs', { duration: 2000 }) + return } - router.push(`/shop/checkout?product_id=${activeVariant.id}&qty=${quantity}`); + router.push(`/shop/checkout?product_id=${activeVariant.id}&qty=${quantity}`) } + const TabButton = ({ children, name }) => ( + <button + type="button" + className={`font-medium pb-1 ${activeTab == name ? 'text-red_r-11 border-b border-red_r-10' : 'text-gray_r-11'}`} + onClick={() => setActiveTab(name)} + > + { children } + </button> + ) + return ( <> <Header title={`${product.name} - Indoteknik`}/> @@ -203,7 +214,7 @@ export default function ProductDetail({ product }) { product.variants.map((variant) => { return ( <option key={variant.id} value={variant.id}>{variant.attributes.join(', ')}</option> - ); + ) }) ) : ( <option key={product.variants[0].id} value={product.variants[0].id}>{product.variants[0].name}</option> @@ -234,41 +245,42 @@ export default function ProductDetail({ product }) { <LineDivider /> <div className="p-4"> - <h2 className="font-bold mb-2">Detail Produk</h2> - <div className="flex py-2 justify-between items-center gap-x-1"> - <h3 className="text-gray-900">Jumlah Varian</h3> - <p className="text-gray-800">{product.variant_total} Varian</p> + <h2 className="font-bold mb-4">Informasi Produk</h2> + <div className="flex gap-x-3 mb-4"> + <TabButton name="specification">Spesifikasi</TabButton> + <TabButton name="description">Deskripsi</TabButton> + <TabButton name="information">Info Penting</TabButton> </div> - <div className="flex py-2 justify-between items-center gap-x-1"> - <h3 className="text-gray-900">No. SKU</h3> - <p className="text-gray-800" id="sku_number">SKU-{activeVariant.id}</p> + + <div className={`border border-gray_r-6 rounded divide-y ${activeTab == 'specification' ? 'block' : 'hidden'}`}> + <ProductSpecification label="Jumlah Varian"> + <p className="text-gray-800">{product.variant_total} Varian</p> + </ProductSpecification> + <ProductSpecification label="Nomor SKU"> + <p className="text-gray-800" id="sku_number">SKU-{activeVariant.id}</p> + </ProductSpecification> + <ProductSpecification label="Part Number"> + <p className="text-gray-800" id="part_number">{activeVariant.code}</p> + </ProductSpecification> + <ProductSpecification label="Stok"> + <div className="flex gap-x-2" id="stock"> + {activeVariant.stock > 0 ? (activeVariant.stock > 5 && ( + <> + <div className="badge-solid-red">Ready Stock</div> + <div className="badge-gray">{activeVariant.stock > 5 ? '> 5' : '< 5'}</div> + </> + )) : '0'} + </div> + </ProductSpecification> + <ProductSpecification label="Part Number"> + <p className="text-gray-800" id="weight">{activeVariant.weight > 0 ? activeVariant.weight : '1'} KG</p> + </ProductSpecification> </div> - <div className="flex py-2 justify-between items-center gap-x-1"> - <h3 className="text-gray-900">Part Number</h3> - <p className="text-gray-800" id="part_number">{activeVariant.code}</p> - </div> - <div className="flex py-2 justify-between items-center gap-x-1"> - <h3 className="text-gray-900">Stok</h3> - <div className="flex gap-x-2" id="stock"> - {activeVariant.stock > 0 ? (activeVariant.stock > 5 && ( - <> - <div className="badge-solid-red">Ready Stock</div> - <div className="badge-gray">{activeVariant.stock > 5 ? '> 5' : '< 5'}</div> - </> - )) : '0'} - </div> - </div> - <div className="flex py-2 justify-between items-center gap-x-1"> - <h3 className="text-gray-900">Berat Barang</h3> - <p className="text-gray-800" id="weight">{activeVariant.weight > 0 ? activeVariant.weight : '1'} KG</p> - </div> - </div> - - <LineDivider /> - - <div className="p-4"> - <h2 className="font-bold mb-4">Deskripsi Produk</h2> - <div className="text-gray-800 leading-7" dangerouslySetInnerHTML={{__html: (product.description != '' ? product.description : 'Belum ada deskripsi produk.')}}></div> + + <div + className={`text-gray-800 leading-7 ${activeTab == 'description' ? 'block' : 'hidden'}`} + dangerouslySetInnerHTML={{__html: (product.description != '' ? product.description : 'Belum ada deskripsi produk.')}} + ></div> </div> <LineDivider /> @@ -280,5 +292,14 @@ export default function ProductDetail({ product }) { <Footer /> </Layout> </> - ); + ) +} + +const ProductSpecification = ({ children, ...props }) => { + return ( + <div className="flex p-3 justify-between items-center gap-x-1"> + <h3 className="text-gray-900">{ props.label }</h3> + { children } + </div> + ) }
\ No newline at end of file |
